use crate::class_file::ClassFile;
use crate::constant_pool::ConstantPool;
use crate::field::Field;
use crate::method::Method;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Class {
    _access_flags: u16,
    pub(crate) constant_pool: ConstantPool,
    pub(crate) methods: HashMap<String, Method>,
    pub(crate) fields: HashMap<String, Field>,
    pub(crate) this_class: String,
    pub(crate) super_class: String,
}

impl Class {
    pub fn method(&self, name_and_type: &str) -> Option<&Method> {
        self.methods.get(name_and_type)
    }
}

impl From<ClassFile> for Class {
    fn from(class_file: ClassFile) -> Self {
        let ClassFile {
            access_flags,
            constant_pool,
            this_class,
            super_class,
            methods,
            ..
        } = class_file;

        let constant_pool = ConstantPool::from(constant_pool);
        Class {
            _access_flags: access_flags,
            methods: methods
                .into_iter()
                .map(|info| Method::from(info, &constant_pool))
                .map(|method| (format!("{}:{}", method.name, method.descriptor), method))
                .collect(),
            fields: HashMap::new(),
            this_class: constant_pool.class(this_class),
            super_class: constant_pool.class(super_class),
            constant_pool,
        }
    }
}
